home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / bipl.zip / PROCS.ZIP / PACKUNPK.ICN < prev    next >
Text File  |  1992-09-28  |  4KB  |  131 lines

  1. ############################################################################
  2. #
  3. #    File:     packunpk.icn
  4. #
  5. #    Subject:  Procedures to pack and unpack packed-decimal strings
  6. #
  7. #    Author:   C. Tenaglia (modified by Richard L. Goerwitz)
  8. #
  9. #    Date:     June 1, 1991
  10. #
  11. ###########################################################################
  12. #
  13. #    Version:  1.2
  14. #
  15. ###########################################################################
  16. #
  17. #      Integers written directly as strings occupy much more space
  18. #  than they need to.  One easy way to shrink them a bit is to "pack"
  19. #  them, i.e.  convert each decimal digit into a four-byte binary
  20. #  code, and pack these four-bit chunks into eight-bit characters,
  21. #  which can be written to a file.
  22. #
  23. #      Interestingly, packing decimal strings in this manner lends
  24. #  itself to unpacking by treating each character as a base-10
  25. #  integer, and then converting it to base-16.  Say we have an input
  26. #  string "99."  Pack() would convert it to an internal representation
  27. #  of char(16*9 + 9), i.e. char(153).  Unpack would treat this
  28. #  char(153) representation as a base-10 integer, and convert it to
  29. #  base 16 (i.e. 10r153 -> 16r99).  The 99 is, of course, what we
  30. #  started with.
  31. #
  32. #      Note that two unpack routines are provided here:  The first, by
  33. #  Tanaglia, utilizes radcon.icn from the IPL.  The second, by
  34. #  Goerwitz, does not.  They utilize very different methods, but both
  35. #  amount to basically the same thing.  Goerwitz's routine returns an
  36. #  integer, though, and has no "width" argument.
  37. #
  38. ############################################################################
  39. #
  40. #  Links:  radcon.icn
  41. #
  42. ############################################################################
  43.  
  44. link radcon
  45.  
  46. procedure pack(num,width)     
  47.  
  48.     local int, sign, prep, packed, word
  49.  
  50.     int := integer(num) | fail
  51.     # There's really no need to store the sign if it's positive, UNLESS
  52.     # you are using this program to store packed decimal integers for
  53.     # access by other programs on certain mainframes that always store
  54.     # the sign.
  55.     # if int < 0 then sign := "=" else sign := "<"
  56.     if int < 0 then sign := "=" else sign := ""
  57.     prep   := string(abs(int)) || sign
  58.     packed := ""
  59.     if (*prep % 2) ~= 0 then prep := "0" || prep
  60.  
  61.     prep ? {
  62.     while word := move(2) do {
  63.         if pos(0)
  64.         then packed ||:= char(integer(word[1])*16 + ord(word[2])-48)
  65.         else packed ||:= char(integer(word[1])*16 + integer(word[2]))
  66.     }
  67.     }
  68.  
  69.     /width := *packed
  70.     return right(packed, width, "\0")
  71.  
  72. end
  73.  
  74.  
  75.  
  76. procedure unpack(val,width)   
  77.  
  78.     # THIS PROCEDURE UNPACKS A VALUE INTO A STRING-INTEGER. USING THIS
  79.     # CODE SEGMENT REQUIRES LINKING WITH RADCON FROM THE IPL.
  80.  
  81.     local tmp, number, tens, ones, sign
  82.  
  83.     tmp  := ""
  84.     sign := 1
  85.  
  86.     every number := ord(!val) do
  87.     tmp ||:= right(map(radcon(number,10,16),&lcase,&ucase),2,"0")
  88.  
  89.     if tmp[-1] == ("B" | "D") then {
  90.     sign := -1
  91.     # In this configuration, the sign field is only present if the
  92.     # integer is negative.  If you have set up pack to register posi-
  93.     # tive values in the sign field, place the following line after
  94.     # the "if-then" expression.
  95.     tmp[-1] :=  ""
  96.     }
  97.     tmp    *:= sign
  98.     /width  := *string(tmp)
  99.  
  100.     return right(string(tmp), width)
  101.  
  102. end
  103.  
  104.  
  105.  
  106. procedure unpack2(val)
  107.  
  108.     # THIS PROCEDURE UNPACKS A VALUE INTO AN STRING-INTEGER.
  109.     # Note:  Unpack2 assumes that pack is not recording positive
  110.     # sign values.
  111.  
  112.     local unpacked, int
  113.  
  114.     unpacked := ""
  115.     val ? {
  116.     while int := ord(move(1)) do {
  117.         unpacked ||:= string(iand(2r11110000,int) / 16)
  118.         if pos(0) then {
  119.         if iand(2r00001111,int) = 13 then {
  120.             unpacked := "-" || unpacked
  121.             break
  122.         }
  123.         }
  124.         unpacked ||:= string(iand(2r00001111,int))
  125.     }
  126.     }
  127.  
  128.     return integer(unpacked)
  129.  
  130. end
  131.